前一篇文章帶大家看了網路爬蟲的種類,下次看到類似的名詞時能想到那一類的爬蟲的特性。
本篇將帶各位實作爬取 PTT 的爬蟲,在開始之前請各位準備好虛擬環境,各位記得將 pipenv --venv
放入 Vscode Settings,不知道如何設定可以回去看這篇 【Day 02】- 網路爬蟲環境設定(Python、pipenv、Vscode) 。
這次爬取的網站是 PTT 八卦版 https://www.ptt.cc/bbs/Gossiping/index.html,會使用到 requests
與 beautifulSoup
。
可以繞過已滿 18 歲的確認。
能夠爬取當前頁面的所有文章。
首先先引入會用到的函式庫,並將目標網址存於 url。
import requests
from bs4 import BeautifulSoup
url = 'https://www.ptt.cc/bbs/Gossiping/index.html'
直接向目標網址發一個 GET 之後看看回應物件的 text,發現並不是我們要的文章內容,而是一個確認是否 18 歲的頁面。我們能用 google 直接瀏覽該頁面也會發現需要點擊已滿 18 隨才能進入網站內容。
resp = requests.get(url)
print(resp.text)
'''已將部分不必要內容刪除
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>批踢踢實業坊</title>
</head>
<body>
<div class="bbs-screen bbs-content">
<div class="over18-notice">
<p>本網站已依網站內容分級規定處理</p>
<p>警告︰您即將進入之看板內容需滿十八歲
方可瀏覽。</p>
<p>若您尚未年滿十八歲,請點選離開。若您
已滿十八歲,亦不可將本區之內容派發、傳閱、出售、
出租、交給或借予年齡未滿18歲的人士瀏覽,或將本網
站內容向該人士出示、播放或放映。</p>
</div>
</div>
<div class="bbs-screen bbs-content center clear">
<form action="/ask/over18" method="post">
<input type="hidden" name="from" value="/bbs/Gossiping/index.html">
<div class="over18-button-container">
<button class="btn-big" type="submit" name="yes" value="yes">我同意,我已年滿十八歲<br><small>進入</small></button>
</div>
<div class="over18-button-container">
<button class="btn-big" type="submit" name="no" value="no">未滿十八歲或不同意本條款<br><small>離開</small></button>
</div>
</form>
</div>
</body>
</html>
'''
既然透過點擊已滿 18 歲可以成功進入八卦版,以及下次再進入網站不必再次點擊,我們能直覺的聯想到應該是用了 cookies 這項技術。
我們能用 https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm 來檢視點擊已滿 18 歲後,該網域下的 cookies。
發現有個 cookies 名為 over18 數值為 1,要確認是否為這個 cookies 可以將其刪除後再重新整理,會發現需要再次點擊已滿 18 歲。
了解到是 over18 這個 cookies 來紀錄是否點擊過已滿 18 歲,我們能將這個 cookies 當作 requests.get
的參數一同傳入。
將上方的程式加上了 cookies 傳入。 於是可以正確取得文章內容了。
cookies = {
'over18': '1'
}
resp = requests.get(url, cookies=cookies)
print(resp.text)
''' 已將部分不必要內容刪除
<!DOCTYPE html>
<html>
<body>
<a href="/bbs/Gossiping/M.1632305989.A.5E0.html">[協尋] 橘貓咪嚕快點回家!(大安區)</a>
</div>
<div class="meta">
<div class="author">k020231310</div>
<div class="article-menu">
<div class="trigger">⋯</div>
<div class="dropdown">
<div class="item"><a href="/bbs/Gossiping/search?q=thread%3A%5B%E5%8D%94%E5%B0%8B%5D+%E6%A9%98%E8%B2%93%E5%92%AA%E5%9A%95%E5%BF%AB%E9%BB%9E%E5%9B%9E%E5%AE%B6%EF%BC%81%EF%BC%88%E5%A4%A7%E5%AE%89%E5%8D%80%EF%BC%89">搜尋同標題文章</a></div>
<div class="item"><a href="/bbs/Gossiping/search?q=author%3Ak020231310">搜尋看板內 k020231310 的文章
</a></div>
</div>
</div>
<div class="date"> 9/22</div>
<div class="mark"></div>
</body>
</html>
'''
有了包含文章內容的資料後,要用 BeautifulSoup 進行資料清洗,將我們要的內容清理出來。
可以用開發工具的選取功能選取文章,發現文章的元素都放在 class 為 r-ent 的 下面。
可以看到該 div 下面確實包含該文章的資訊。
我們能先爬取文章內容、文章連結及作者,這邊用到了 BeautifulSoup 的基本操作,還不了解的讀者能到 {Day 10} 看歐。
import requests
from bs4 import BeautifulSoup
url = 'https://www.ptt.cc/bbs/Gossiping/index.html'
cookies = {
'over18': '1'
}
resp = requests.get(url, cookies=cookies)
soup = BeautifulSoup(resp.text, 'html5lib')
arts = soup.find_all('div', class_='r-ent')
for art in arts:
title = art.find('div', class_='title').getText().strip()
link = 'https://www.ptt.cc' + \
art.find('div', class_='title').a['href'].strip()
author = art.find('div', class_='author').getText().strip()
print(f'title: {title}\nlink: {link}\nauthor: {author}')
'''
title: [問卦] 恆大要爆了沒?經濟要崩了沒?魯蛇要怎翻身
link: https://www.ptt.cc/bbs/Gossiping/M.1632408620.A.966.html
author: com2
title: [問卦] 玉山銀行是不是5倍券的最大贏家
link: https://www.ptt.cc/bbs/Gossiping/M.1632408638.A.4A5.html
author: nnnn7615
title: Re: [新聞] 6成7台男月薪沒5萬不敢教女友 北部女:
link: https://www.ptt.cc/bbs/Gossiping/M.1632408645.A.5EB.html
author: bandwandbenz
title: [問卦] 迴轉壽司的迴轉484很多餘?
link: https://www.ptt.cc/bbs/Gossiping/M.1632408657.A.B69.html
author: wang111283
...
'''
今天實作了 Requests 中攜帶 cookies ,讓網路爬蟲不會被 18 歲驗證擋住。
明天將繼續 PTT 爬蟲,目前只會爬取當前文章,其實只要能爬取下一頁網址,之後再向下一頁發 GET,便可達到持續爬取。
PTT 八卦版 : https://www.ptt.cc/bbs/Gossiping/index.html